/**
 * 给定树，节点上有字符，有若干个询问(v, h)，问子树v上深度为h的节点是否能够通过重排序构成回文串。
 * 注意节点深度是指整个树上的深度，因此是固定的。
 * 实际上就是问对应节点的字符数量，是否奇数个字母的数量少于等于1。
 * 由于只涉及到奇偶，可以使用一个26位二进制数表示数量，只需检查1的位数小于等于1即可。
 * 令cnt[d]表示表示深度为d的情况下的字符数量，使用DSU来维护cnt数组
 * 然后对每个子树u，如果有关于它的问题，例如(u, h)，则查询当时的cnt[h]、且记录下来即可。
 */
#include <bits/stdc++.h>
using namespace std;

struct dsu_on_tree_t{

using vi = vector<int>;

int N;
vector<vi> G; // 树, 1-index

struct node_t{ // 树链剖分的结构
    int size; 
    int hson; // 重儿子，这里是原树编号    
    int nid;  // 在树链剖分中的新编号
    int mdes; // 本子树全部在[nid, mdes]之间, 这是剖分编号
};
vector<node_t> Nodes;
vi New2Old;   // 剖分的编号为i，则原树节点编号为New2Old[i], 显然有Nodes[New2Old[i]].nid == i
int TimeStamp;
int Root;
vector<int> Depth;

string S;
vector<int> Ans;

vector<vector<pair<int, int>>> Questions;

vector<int> Cnt;

void init(int n){
    N = n;
    G.assign(N + 1, {});
    Nodes.assign(N + 1, {0, 0, 0, 0});
    New2Old.assign(N + 1, 0);
    TimeStamp = 0;
    Depth.assign(N + 1, 0);
    Cnt.assign(N + 1, 0);
}

void mkDiEdge(int a, int b){
    G[a].push_back(b);
}

void mkBiEdge(int a, int b){
    mkDiEdge(a, b);
    mkDiEdge(b, a);
}

void dfsHeavy(int u, int p){ // 递归重儿子
    Depth[u] = Depth[p] + 1;
    auto & n = Nodes[u];
    n.size = 1;
    New2Old[n.nid = ++TimeStamp] = u;

    for(auto v : G[u]){
        if(v == p) continue;

        dfsHeavy(v, u);
        n.size += Nodes[v].size;
        if(Nodes[n.hson].size < Nodes[v].size) n.hson = v;
    }

    n.mdes = TimeStamp;
    return;
}


void dfs(int u, int p, bool keep){ // 递归
    const auto & n = Nodes[u];
    for(auto v : G[u]){
        if(v == p or v == n.hson) continue;
        dfs(v, u, false);
    }
    /// 最后递归重儿子
    if(n.hson) dfs(n.hson, u, true);

    /// 以下为统计u节点及其轻儿子
    if(n.hson){
        for(int i=n.nid;i<Nodes[n.hson].nid;++i){
            auto t = S[New2Old[i]] - 'a';
            Cnt[Depth[New2Old[i]]] ^= (1 << t);
        }
        for(int i=Nodes[n.hson].mdes+1;i<=n.mdes;++i){
            auto t = S[New2Old[i]] - 'a';
            Cnt[Depth[New2Old[i]]] ^= (1 << t);  
        }
    }else{ // 只有一个节点
        Cnt[Depth[u]] = 1 << (S[u] - 'a');
    }

    /// 此时可以回答问题
    for(const auto & pp : Questions[u]){
        auto h = pp.first;
        bool b = true;
        int c = 0;
        for(int i=0;i<26;++i){
            if((1 << i) & Cnt[h])if(++c > 1){b = false; break;}
        }
        Ans[pp.second] = b ? 1 : 0;
    }

    /// 是否清空u子树对即时数据的影响
    if(not keep){
        /// 清空
        for(int i=n.nid;i<=n.mdes;++i) {
            Cnt[Depth[New2Old[i]]] = 0;
        }
    }
    return;
}


}Tree;

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, q; cin >> n >> q;
    Tree.init(n);    
    for(int a,i=2;i<=n;++i){
        cin >> a;
        Tree.mkDiEdge(a, i);
    }
    cin >> Tree.S;
    Tree.S = " " + Tree.S;
    
    Tree.Questions.assign(n + 1, {});
    Tree.Ans.assign(q, 0);
    for(int u,h,i=0;i<q;++i){
        cin >> u >> h;
        Tree.Questions[u].emplace_back(h, i);
    }
    
    Tree.dfsHeavy(1, 0);
    Tree.dfs(1, 0, true);
    for(auto i : Tree.Ans) cout << (i ? "Yes\n" : "No\n");
    return 0;
}
